﻿@page "/"
@page "/Hello"
@using LiveChartsCore.Defaults;
@using LiveChartsCore.Measure;
@using LiveChartsCore.SkiaSharpView.Blazor
@using LiveChartsCore;
@using LiveChartsCore.SkiaSharpView;
@using System.Collections.ObjectModel;
@using LiveChartsCore.SkiaSharpView.Drawing.Geometries;
@using LiveChartsCore.SkiaSharpView.Painting;
@using LiveChartsCore.SkiaSharpView.Painting.Effects;
@using LiveChartsCore.SkiaSharpView.VisualElements;
@using SkiaSharp;
@inject IJSRuntime JS;

<div class="container-fluid">
    <div class="row">
        <div class="col-12 mb-5">
            <h1 id="lvc-hello" class="font-display text-center bold-600">
                <span class="text-live">Live</span><span class="text-charts">Charts2</span>
            </h1>
            <p class="text-muted text-center mb-3">
                Open source data visualization library for dotnet completely written in C#.<br />
                This site is a Blazor app (net 7), the code is available 
                <a href="https://github.com/beto-rodriguez/LiveCharts2/tree/master/samples/BlazorSample">here</a>.
            </p>
        </div>

        <div class="col-xl-5">
            <div class="d-flex justify-content-end">
                <div class="present-livecharts-container">
                    <h1 id="hello-title" class="mb-4 text-charts fw-bolder"></h1>
                    <p id="hello-description" class="text-muted"></p>
                    <pre><code id="hello-code" class="language-cs"></code></pre>
                </div>
            </div>
        </div>
        <div class="col-xl-7">
            <div id="cartesian-chart" class="bg-white shadow chart-sample rounded mx-auto mt-5">
                <CartesianChart @ref="Chart" />
            </div>

            <div id="pie-chart" class="bg-white shadow chart-sample rounded mx-auto mt-5">
                <PieChart @ref="PieChart" />
            </div>

            <div id="gauge-chart" class="bg-white shadow chart-sample rounded mx-auto mt-5">
                <PieChart @ref="GaugeChart" />
            </div>

            <div id="polar-chart" class="bg-white shadow chart-sample rounded mx-auto mt-5">
                <PolarChart @ref="PolarChart" />
            </div>

            <div id="geo-chart" class="bg-white shadow chart-sample rounded mx-auto mt-5">
                <GeoMap @ref="GeoMap" MapProjection="LiveChartsCore.Geo.MapProjection.Mercator" />
            </div>

            <div id="ba-bye" class="chart-sample mx-auto">
                <p class="text-center text-muted">
                    LiveCharts provides controls for any UI framework (console and server-side is also supported). <br />
                    <small class="text-center text-muted">
                        The minimum requirement for .Net framework is .Net 4.6.2 and is compatible with .NET standard 2.0.
                    </small>
                </p>

                <div class="d-flex flex-row flex-wrap justify-content-start align-items-center">
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/bot.svg" alt="maui">
                        </div>
                        <div>Maui</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/uno.png" alt="uno" class="uno-img-sm">
                        </div>
                        <div>Uno Platform</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/avalonia.svg" alt="windows">
                        </div>
                        <div>Avalonia</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div>EtoForms</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/xamarin.svg" alt="xamarin" />
                        </div>
                        <div>Xamarin</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/blazor.svg" alt="blazor" />
                        </div>
                        <div>Blazor Wasm</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/windows.svg" alt="windows">
                        </div>
                        <div>WPF</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/windows.svg" alt="windows">
                        </div>
                        <div>WinForms</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/logo-winui.png" class="platform-image mw-100" />
                        </div>
                        <div>WinUI</div>
                    </div>
                    <div class="d-flex flex-row align-items-center btn btn-light platform-btn shadow-sm m-2 bg-white">
                        <div class="me-3">
                            <img src="./platforms/windows.svg" alt="windows">
                        </div>
                        <div>UWP</div>
                    </div>
                </div>

                <h5 class="text-center fw-bolder my-4">
                    Want to see more?
                </h5>

                <p class="text-muted mb-4">
                    All this site and the library is open source, you can
                    <a href="https://github.com/beto-rodriguez/LiveCharts2/tree/master/samples/BlazorSample">clone this site</a>
                    to explore more, this repo/site also includes multiple interesting examples that you could be interested in, the
                    following samples are running on Blazor WASM, take a look!
                </p>

                <div class="row">
                    <div class="col-lg-4 my-3">
                        <a class="text-decoration-none" href="/Lines/Zoom">
                            <div class="gallery-card shadow p-2 bg-white">
                                <div class="text-center">
                                    <img src="https://raw.githubusercontent.com/beto-rodriguez/LiveCharts2/dev//docs/samples/lines/zoom/result.gif" alt="zoom">
                                </div>
                                <h5 class="gallery-title">Zooming and panning</h5>
                            </div>
                        </a>
                    </div>

                    <div class="col-lg-4 my-3">
                        <a class="text-decoration-none" href="/Bars/DelayedAnimation">
                            <div class="gallery-card shadow p-2 bg-white">
                                <div class="text-center">
                                    <img src="https://raw.githubusercontent.com/beto-rodriguez/LiveCharts2/dev//docs/samples/bars/delayedAnimation/result.gif" alt="delayedAnimation">
                                </div>
                                <h5 class="gallery-title">Delayed animations</h5>
                            </div>
                        </a>
                    </div>

                    <div class="col-lg-4 my-3">
                        <a class="text-decoration-none" href="/Events/AddPointOnClick">
                            <div class="gallery-card shadow p-2 bg-white">
                                <div class="text-center">
                                    <img src="https://raw.githubusercontent.com/beto-rodriguez/LiveCharts2/dev//docs/samples/events/addPointOnClick/result.gif" alt="addPointOnClick">
                                </div>
                                <h5 class="gallery-title">Add point on click</h5>
                            </div>
                        </a>
                    </div>
                </div>

                <h5 class="text-center fw-bolder my-4">
                    Repeat the presentation?
                </h5>

                <p class="text-muted mb-4">
                    Refresh your browser 😢 or do a pull request to LiveCharts2 repo with the navigation interaction, PRs are always welcome!
                </p>

            </div>
        </div>

    </div>
</div>

@*<a href="/Browse" class="text-decoration-none btn btn-light text-primary shadow">Browse samples</a>*@

@code {
    public CartesianChart? Chart;
    public PieChart? PieChart;
    public PieChart? GaugeChart;
    public PolarChart? PolarChart;
    public GeoMap? GeoMap;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (Chart is null) return;

        await Sample1();
        await Task.Delay(5000);
        await Sample2();
        await Task.Delay(5000);
        await Sample3();
        await Task.Delay(5000);
        await Sample4();
        await Task.Delay(5000);
        await Sample5();
        await Task.Delay(5000);
        await Sample6();
        await Task.Delay(5000);
        await Sample7();
        await Task.Delay(5000);
        await Sample8();
    }

    public async Task Sample1()
    {
        Chart.EasingFunction = EasingFunctions.ExponentialOut;
        Chart.AnimationsSpeed = TimeSpan.FromSeconds(1.5);

        Chart.Series = new ISeries[]
        {
            new LineSeries<int> { Values = new[] { 6, 7, 2, 4, 2 } },
            new ColumnSeries<int> { Values = new[] { 1, 5, 4, 5, 7 } }
        };

        await JS.InvokeVoidAsync("hlElements",
            "Simple, intuitive",
            "A few lines of code can build stunning, animated and interactive charts.",
            @"Series = new ISeries[]
{
    new LineSeries&lt;int>
    {
        Values = new[] { 6, 7, 2, 4, 2 }
    },
    new ColumnSeries&lt;int>
    {
        Values = new[] { 1, 5, 4, 5, 7 }
    }
};");
    }

    public async Task Sample2()
    {
        await JS.InvokeVoidAsync("hlElements",
            "Animate everything",
            "Any change is animated and automatically updated in the UI.",
                @"var values = new ObservableCollection&lt;ObservableValue>
{
    new(2), new(4), new(2), new(6)
};

Series = new ISeries[]
{
    new LineSeries&lt;ObservableValue>
    {
        Values = values
    }
};

values[2].Value = -5;
values[2].Value = 5;
values[2].Value = 10;

values.Add(new(5));");

        Chart.AnimationsSpeed = TimeSpan.FromSeconds(1.5);
        Chart.EasingFunction = EasingFunctions.BounceOut;

        var values = new ObservableCollection<ObservableValue>
        {
            new(2), new(4), new(2), new(6)
        };

        var lineSeries = new LineSeries<ObservableValue>
        {
            Values = values,
            GeometrySize = 0,
            GeometryFill = null,
            GeometryStroke = null,
            LineSmoothness = 1,
            Fill = null,
            Stroke = new LinearGradientPaint(
                new[] { new SKColor(45, 64, 89), new SKColor(255, 212, 96) }) { StrokeThickness = 20 }
        };

        Chart.Series = new ISeries[]
        {
            lineSeries
        };

        await Task.Delay(2500);

        values[2].Value = -5;
        await Task.Delay(2500);

        values[2].Value = 5;
        await Task.Delay(2500);

        values[2].Value = 10;
        await Task.Delay(2500);

        values.Add(new(5));
        values.Add(new(8));
        values.Add(new(7));
        values.Add(new(12));
        values.Add(new(10));
        values.Add(new(10));
        values.Add(new(9));
        values.Add(new(12));
        values.Add(new(13));
        values.Add(new(12));
        values.Add(new(9));
        values.Add(new(14));
        lineSeries.LineSmoothness = 0;
    }

    public async Task Sample3()
    {
        Chart.EasingFunction = EasingFunctions.PolinominalInOut;
        Chart.AnimationsSpeed = TimeSpan.FromSeconds(1);

        await JS.InvokeVoidAsync("hlElements",
            "Flexible",
            "Charts look as your app needs, everything is customizable, the library also provides multiple ready-to-go themes (WIP).",
            @"// nothing to show here :(");

        var blue = new SKColor(25, 118, 210);
        var yellow = new SKColor(198, 167, 0);
        var gray = new SKColor(207, 216, 220);
        var dark = new SKColor(28, 49, 58);

        //Chart.LegendPosition = LiveChartsCore.Measure.LegendPosition.Right;

        Chart.Series = new ISeries[]
        {
            new LineSeries<double>
            {
                Name = "Sales",
                LineSmoothness = 1,
                Values = new double[] { 14, 13, 14, 15, 17 },
                ScalesYAt = 0
            },
            new LineSeries<double>
            {
                Name = "Requests",
                LineSmoothness = 1,
                Values = new double[] { 11, 12, 13, 10, 13 },
                ScalesYAt = 0
            },
            new LineSeries<double>
            {
                Name = "Also this!",
                LineSmoothness = 1,
                Values = new double[] { 533, 586, 425, 579, 518 },
                ScalesYAt = 1
            },
        };
        Chart.YAxes = new Axis[]
        {
            new Axis
            {
                TicksPaint = new SolidColorPaint(dark, 1),
                SubticksPaint = new SolidColorPaint(dark, 1),
                DrawTicksPath = true
            },
            new Axis
            {
                TicksPaint = new SolidColorPaint(dark, 1),
                SubticksPaint = new SolidColorPaint(dark, 1),
                DrawTicksPath = true
            }
        };
        Chart.XAxes = new Axis[]
        {
            new Axis // the "units" and "tens" series will be scaled on this axis
            {
                TicksPaint = new SolidColorPaint(dark, 1),
                SubticksPaint = new SolidColorPaint(dark, 1),
                DrawTicksPath = true
            }
        };

        await Task.Delay(2000);

        var seriesCollection = Chart.Series.ToArray();

        var s1 = (LineSeries<double>)seriesCollection[0];

        s1.Stroke = null;
        s1.GeometryFill = null;
        s1.GeometryStroke = null;
        s1.Fill = new SolidColorPaint(blue.WithAlpha(50));
        await Task.Delay(200);

        var s2 = (LineSeries<double>)seriesCollection[1];
        s2.Stroke = null;
        s2.GeometryFill = null;
        s2.GeometryStroke = null;
        s2.Fill = new SolidColorPaint(blue.WithAlpha(150));
        await Task.Delay(200);

        var s3 = (LineSeries<double>)seriesCollection[2];
        s3.Stroke = null;
        s3.GeometryFill = null;
        s3.GeometryStroke = null;
        s3.Fill = new SolidColorPaint(yellow.WithAlpha(150));
        await Task.Delay(800);

        s1.LineSmoothness = 0.1;
        s2.LineSmoothness = 0.1;
        s3.LineSmoothness = 0.1;
        await Task.Delay(800);

        s1.DataPadding = new LiveChartsCore.Drawing.LvcPoint(0, 0);
        s2.DataPadding = new LiveChartsCore.Drawing.LvcPoint(0, 0);
        s3.DataPadding = new LiveChartsCore.Drawing.LvcPoint(0, 0);
        await Task.Delay(800);

        Chart.Title = new LabelVisual
        {
            Padding = new LiveChartsCore.Drawing.Padding(12),
            TextSize = 20,
            Paint = new SolidColorPaint(dark),
            Text = "Nice chart you have there!"
        };
        await Task.Delay(800);

        var y1 = (Axis)Chart.YAxes.ToArray()[0];
        //y1.TextSize = 15;
        y1.LabelsPaint = new SolidColorPaint(blue);
        y1.SeparatorsPaint = new SolidColorPaint(gray);
        y1.SubseparatorsPaint = new SolidColorPaint(gray.WithAlpha(100));
        y1.TicksPaint = new SolidColorPaint(blue, 3);
        y1.SubticksPaint = new SolidColorPaint(blue, 3);

        var y2 = (Axis)Chart.YAxes.ToArray()[1];
        //y2.TextSize = 15;
        y2.LabelsPaint = new SolidColorPaint(yellow);
        y2.TicksPaint = new SolidColorPaint(yellow, 3);
        y2.SubticksPaint = new SolidColorPaint(yellow, 3);
        y2.Position = LiveChartsCore.Measure.AxisPosition.End;
        y2.ShowSeparatorLines = false;

        await Task.Delay(2000);

        var x = (Axis)Chart.XAxes.ToArray()[0];

        x.MinStep = 1;
        x.ForceStepToMin = true;
        x.SubticksPaint = null;
        x.SeparatorsPaint = new SolidColorPaint(dark);
        x.SubseparatorsPaint = new SolidColorPaint(dark);
        await Task.Delay(800);

        x.SeparatorsAtCenter = false;
        await Task.Delay(800);

        x.SeparatorsPaint = new SolidColorPaint
        {
            Color = gray,
            StrokeThickness = 2,
            PathEffect = new DashEffect(new float[] { 6, 6 })
        };
        x.SubseparatorsPaint = new SolidColorPaint(gray.WithAlpha(100));
        await Task.Delay(800);

        Chart.DrawMarginFrame = new DrawMarginFrame
        {
            Fill = new SolidColorPaint(gray.WithAlpha(50)) { ZIndex = -1 }
        };
    }

    public async Task Sample4()
    {
        PieChart.EasingFunction = EasingFunctions.BounceOut;
        PieChart.AnimationsSpeed = TimeSpan.FromSeconds(1.5);

        var outer = 10;
        PieChart.Series = new[] { 30, 20, 15, 10, 8, 4 }
            .AsLiveChartsPieSeries((value, series) =>
            {
                series.InnerRadius = 50;
                series.OuterRadiusOffset = outer;
                outer = outer - 25;
            });

        await JS.InvokeVoidAsync("hlElements",
            "Pie Charts",
            "LiveCharts also includes PieCharts",
            @"PieChart.Series = new[] { 30, 20, 15, 10, 8, 4 }
.AsLiveChartsPieSeries((value, series) =>
{
    series.InnerRadius = 50;
    series.MaxOuterRadius = outer;
    outer = outer - 0.1;
});");

        await Task.Delay(3000);
        PieChart.InitialRotation = -90;

        await Task.Delay(3000);
        PieChart.IsClockwise = false;
    }

    public async Task Sample5()
    {
        GaugeChart.EasingFunction = EasingFunctions.QuadraticOut;
        GaugeChart.AnimationsSpeed = TimeSpan.FromSeconds(1.5);

        var vanesa = new ObservableValue(30);
        var charles = new ObservableValue(50);
        var ana = new ObservableValue(70);

        GaugeChart.Series = new GaugeBuilder()
            .WithLabelsSize(20)
            .WithLabelsPosition(PolarLabelsPosition.Start)
            .WithLabelFormatter(point => $"{point.Coordinate.PrimaryValue} {point.Context.Series.Name}")
            .WithInnerRadius(20)
            .WithOffsetRadius(8)
            .WithBackgroundInnerRadius(20)

            .AddValue(vanesa, "Vanessa")
            .AddValue(charles, "Charles")
            .AddValue(ana, "Ana")

            .BuildSeries();

        GaugeChart.InitialRotation = 45;
        GaugeChart.MaxAngle = 270;
        GaugeChart.Total = 100;

        await JS.InvokeVoidAsync("hlElements",
            "Gauges",
            "LiveCharts also includes PieCharts, Gauges",
            @"GaugeChart.Series = new GaugeBuilder()
    .WithLabelsSize(20)
    .WithLabelsPosition(PolarLabelsPosition.Start)
    .WithLabelFormatter(point => $""{point.PrimaryValue} {point.Context.Series.Name}"")
    .WithInnerRadius(20)
    .WithOffsetRadius(8)
    .WithBackgroundInnerRadius(20)

    .AddValue(vanesa, ""Vanessa"")
    .AddValue(charles, ""Charles"")
    .AddValue(ana, ""Ana"")

    .BuildSeries();");

        await Task.Delay(3000);
        vanesa.Value = 80;
        charles.Value = 20;
        ana.Value = 50;

        await Task.Delay(3000);
        vanesa.Value = 90;
        charles.Value = 60;
        ana.Value = 70;
    }

    public async Task Sample6()
    {
        PolarChart.EasingFunction = EasingFunctions.QuadraticOut;
        PolarChart.AnimationsSpeed = TimeSpan.FromSeconds(1.5);

        PolarChart.Series = new ISeries[]
        {
            new PolarLineSeries<ObservablePolarPoint>
            {
                Values = new[]
                {
                    new ObservablePolarPoint(0, 10),
                    new ObservablePolarPoint(45, 15),
                    new ObservablePolarPoint(90, 20),
                    new ObservablePolarPoint(135, 25),
                    new ObservablePolarPoint(180, 30),
                    new ObservablePolarPoint(225, 35),
                    new ObservablePolarPoint(270, 40),
                    new ObservablePolarPoint(315, 45),
                    new ObservablePolarPoint(360, 50),
                },
                IsClosed = false,
                Fill = null
            }
        };
        PolarChart.AngleAxes = new PolarAxis[]
        {
            new PolarAxis
            {
                MinLimit = 0,
                MaxLimit = 360,
                Labeler = angle => $"{angle}°",
                ForceStepToMin = true,
                MinStep = 30,
                TextSize = 12
            }
        };

        await JS.InvokeVoidAsync("hlElements",
            "Polar Charts",
            "LiveCharts also includes PieCharts, Gauges, PolarCharts",
            @"PolarChart.Series = new ISeries[]
{
    new PolarLineSeries&lt;ObservablePolarPoint>
    {
        Values = new[]
        {
            new ObservablePolarPoint(0, 10),
            new ObservablePolarPoint(45, 15),
            new ObservablePolarPoint(90, 20),
            // ...
        },
        IsClosed = false,
        Fill = null
    }
};");

        await Task.Delay(3000);
        PolarChart.InitialRotation = -220;

        await Task.Delay(3000);
        PolarChart.TotalAngle = 270;
    }

    public async Task Sample7()
    {
        await JS.InvokeVoidAsync("hlElements",
            "Geo Maps",
            "LiveCharts also includes PieCharts, PolarCharts and GeoMaps",
            @" GeoMap.Series = new HeatLandSeries[]
{
    new HeatLandSeries
    {
        Lands = new HeatLand[]
        {
            new() { Name = ""bra"", Value = 13 },
            new() { Name = ""mex"", Value = 10 },
            new() { Name = ""usa"", Value = 15 },
        }
    }
};");

        GeoMap.Series = new HeatLandSeries[]
        {
            new HeatLandSeries
            {
                Lands = new HeatLand[]
                {
                    new() { Name = "bra", Value = 13 },
                    new() { Name = "mex", Value = 10 },
                    new() { Name = "usa", Value = 15 },
                    new() { Name = "can", Value = 8 },
                    new() { Name = "ind", Value = 12 },
                    new() { Name = "deu", Value = 13 },
                    new() { Name= "jpn", Value = 15 },
                    new() { Name = "chn", Value = 14 },
                    new() { Name = "rus", Value = 11 },
                    new() { Name = "fra", Value = 8 },
                    new() { Name = "esp", Value = 7 },
                    new() { Name = "kor", Value = 10 },
                    new() { Name = "zaf", Value = 12 },
                    new() { Name = "are", Value = 13 }
                }
            }
        };
    }

    public async Task Sample8()
    {
        await JS.InvokeVoidAsync("hlElements",
            "Charts everywhere!",
            "Thanks to SkiaSharp, LiveCharts can now run on Android, iOS, Tizen, MacOS, Linux, Windows and the web, " +
            "using the same code! all this presentation was built with C# (with some JS interop) and it is running in the browser via WebAssembly/Blazor. " +
            "Hello future!",
             "");
    }
}
